package pers.cj.pdos.controller;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import pers.cj.pdos.controller.base.BaseController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.excel.ExcelRefund;
import pers.cj.pdos.excel.ExcelSale;
import pers.cj.pdos.service.IHouseInService;
import pers.cj.pdos.service.IHouseOutService;
import pers.cj.pdos.service.IProviderService;
import pers.cj.pdos.service.IRefundService;
import pers.cj.pdos.task.CleanTempExcelTask;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * <p>
 * 退货单会将商品的状态置为待入库，需要仓库管理员进行入库操作 前端控制器
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Controller
@RequestMapping("/sale")
public class RefundController extends BaseController {

    @Autowired
    IRefundService refundService;
    @Autowired
    IHouseInService houseInService;

    @RequestMapping("/refund")
    @RequiresPermissions("refund:query")
    public String customType() {
        return "/refund/refund";
    }

    @RequiresPermissions("refund:insert")
    @RequestMapping("/refundNew")
    public String refundNew(){
        return "/refund/refundNew";
    }

    @RequiresPermissions("refund:query")
    @RequestMapping("/refundDetail")
    public String refundDetail(Model model, String id){
        model.addAttribute("id",id);
        return "/refund/refundDetail";
    }

    @ResponseBody
    @RequiresPermissions("refund:query")
    @RequestMapping("/refund/getList")
    public ResponseList getList(int page,
                                int limit,
                                String close,
                                String search,
                                String no,
                                String saleNo,
                                String goodsName,
                                String remark,
                                String storeId,
                                String houseId,
                                String settAccountId,
                                String custom,
                                String makeTime1,
                                String makeTime2,
                                String userId,
                                String date1,
                                String date2,
                                String date,
                                String makeUserId,
                                String customId,
                                String status){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();
        List<RefundVo> refundVoList = refundService.listVo(company.getId(),
                page,
                limit,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(saleNo),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                storeId,
                houseId,
                settAccountId,
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                PdosUtils.getViewOrderStoreId(userVo, null),
                PdosUtils.getViewOrderUserId(userVo, userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                makeUserId,
                customId,
                Utils.genInteger(status));
        long count = refundService.count(company.getId(),
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(saleNo),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                storeId,
                houseId,
                settAccountId,
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                PdosUtils.getViewOrderStoreId(userVo, null),
                PdosUtils.getViewOrderUserId(userVo, userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                makeUserId,
                customId,
                Utils.genInteger(status));


        return ResponseList.success(count,refundVoList);
    }

    @ResponseBody
    @RequiresPermissions("refund:insert")
    @RequestMapping("/refund/add")
    public ResponseEntity add(@RequestBody RefundVo refundVo){

        Company company = getCompany();
        BusinessSet businessSet = getBusinessSet();

        if (Utils.isEmpty(refundVo.getNo())){
            return ResponseEntity.fail("编号不能为空");
        }

        if (Utils.isEmpty(refundVo.getRefundGoodsVoList()) && Utils.isEmpty(refundVo.getRefundPacketVoList())){
            return ResponseEntity.fail("您未选择任何商品");
        }

        if (refundVo.getDate() == null){
            return ResponseEntity.fail("业务日期不能为空");
        }

        if (refundVo.getTotalAmt().compareTo(refundVo.getRealAmt()) == -1){
            return ResponseEntity.fail("应退金额不能大于总计金额");
        }

        if (refundService.checkNo(refundVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }

        if (getHouseLocking(refundVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，请更换仓库");
        }

        GoodsUtil goodsUtil = new GoodsUtil(refundVo.getHouseId(), refundVo.getRefundGoodsVoList(), refundVo.getRefundPacketVoList());

        Refund refund = DataUtil.genEntityFromVo(Refund.class, refundVo);
        DataUtil.processEntity(company, refund);
        if (!PdosUtils.houseInOut(businessSet)) {
            refund.setStatus(1);
        }else{
            refund.setStatus(2);
        }
        refund.setMakeUserId(getLoginUserId());
        refund.setMakeTime(new Date());
        refund.setClose(false);
        if (Utils.isEmpty(refund.getSaleId())) {
            refund.setSaleId(null);
        }

        refund.setOldTotalAmt(goodsUtil.getTotalAmount());
        if(!PdosUtils.saleTaxRateFlag(businessSet)) {
            refund.setTax(new BigDecimal(0));
        } else {
            refund.setTax(refund.getOldTotalAmt().multiply(PdosUtils.saleTaxRate(businessSet)));
        }

        List<RefundGoods> refundGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();

        Map<String,Object> snInitMap = new HashMap<>();
        snInitMap.put("inDate", new Date());//设置入库日期
        snInitMap.put("status", 1);//设置状态为未出库
        for (RefundGoodsVo vo:refundVo.getRefundGoodsVoList()) {
            RefundGoods entity = DataUtil.genEntityFromVo(RefundGoods.class, vo);
            DataUtil.processEntity(company,entity);
            entity.setRefundId(refund.getId());
            if(!PdosUtils.saleTaxRateFlag(businessSet)) {
                entity.setTax(new BigDecimal(0));
            } else {
                entity.setTax(entity.getAmount().multiply(PdosUtils.saleTaxRate(businessSet)));
            }
            refundGoodsList.add(entity);

            if (!Utils.isEmpty(vo.getGoodsSnList())){
                for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                    DataUtil.processEntity(company, goodsSn,snInitMap);
                    goodsSnList.add(goodsSn);

                    GoodsSnLog log = new GoodsSnLog();
                    DataUtil.processEntity(company,log);
                    log.setGoodsId(goodsSn.getGoodsId());
                    log.setSn(goodsSn.getSn());
                    log.setType(7);
                    log.setRefundGoodsId(entity.getId());
                    goodsSnLogList.add(log);
                }
            }
        }

        List<RefundPacket> refundPacketList = new ArrayList<>();
        List<RefundPacketGoods> refundPacketGoodsList = new ArrayList<>();

        if (!Utils.isEmpty(refundVo.getRefundPacketVoList())) {
            for (RefundPacketVo vo : refundVo.getRefundPacketVoList()) {
                RefundPacket entity = DataUtil.genEntityFromVo(RefundPacket.class, vo);
                DataUtil.processEntity(company, entity);
                entity.setRefundId(refund.getId());
                if(!PdosUtils.saleTaxRateFlag(businessSet)) {
                    entity.setTax(new BigDecimal(0));
                } else {
                    entity.setTax(entity.getAmount().multiply(PdosUtils.saleTaxRate(businessSet)));
                }
                BigDecimal price = entity.getAmount().divide(entity.getNumber(),4, RoundingMode.HALF_UP); // 套餐实际单价

                BigDecimal packetGoodsTotal = genPacketTotal(vo);//此套餐的总价，用于下面计算实际金额
                for (RefundPacketGoodsVo pgv : vo.getPacketGoodsVoList()) {
                    RefundPacketGoods pg = DataUtil.genEntityFromVo(RefundPacketGoods.class, pgv);
                    DataUtil.processEntity(company, pg);
                    pg.setRefundId(entity.getRefundId());
                    pg.setRefundPacketId(entity.getId());
                    pg.setConvertAmt(price.multiply(pg.getAmount()).divide(packetGoodsTotal,4, RoundingMode.HALF_UP));
                    if(!PdosUtils.saleTaxRateFlag(businessSet)) {
                        pg.setTax(new BigDecimal(0));
                    } else {
                        pg.setTax(pg.getConvertAmt().multiply(PdosUtils.saleTaxRate(businessSet)));
                    }
                    refundPacketGoodsList.add(pg);
                }
                refundPacketList.add(entity);
            }
        }


        refundService.insert(businessSet, refund, refundGoodsList,goodsSnList,goodsSnLogList, refundPacketList, refundPacketGoodsList);


        if (!Utils.isEmpty(goodsSnList) && PdosUtils.houseInOut(businessSet)) {
            //已启用待出库入管理，但是前台传入了sn号，提示
            return ResponseEntity.success("处理成功，管理员在您新增单据过程中启用了出入库管理，录入的sn需要在出库时重新录入");
        }
        return ResponseEntity.success();
    }

    @ResponseBody
    @RequiresPermissions("refund:close")
    @RequestMapping("/refund/close")
    public ResponseEntity close(@RequestBody Refund refund){
        //检查是否已经关闭
        if (refundService.checkClose(refund)){
            return ResponseEntity.fail("该单据已被关闭，不能重复关闭");
        }


        if(houseInService.checkByLinkId(refund.getId())) {
            return ResponseEntity.fail("该订单存在入库单，请先作废对应的入库单");
        }

        try {
            refundService.close(refund);
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("关闭订单失败");
        }
    }


    @ResponseBody
    @RequiresPermissions("refund:insert")
    @RequestMapping("/refund/updateImage")
    public ResponseEntity updateImage(@RequestBody Refund refund){
        try {
            Refund temp = new Refund();
            temp.setId(refund.getId());
            temp.setImage(refund.getImage());
            refundService.updateById(temp);
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("更新图片失败");
        }
    }


    @ResponseBody
    @RequestMapping(value = "/refund/uploadImg", method = RequestMethod.POST)
    public ResponseData uploadImg(MultipartFile imageFile) {
        return processUploadImg(imageFile, "refund");
    }

    @ResponseBody
    @RequestMapping("/refund/getVoById.action")
    public ResponseData getVoById(String id){
        if (Utils.isEmpty(id)){
            return ResponseData.fail("id不能为空");
        }

        RefundVo refundVo = refundService.getVoById(id);
        if (refundVo == null) {
            return ResponseData.fail("id不正确");
        }
        return ResponseData.success(refundVo);
    }

    @ResponseBody
    @RequestMapping("/refund/listVoByIds")
    public ResponseData listVoByIds(@RequestBody List<String> ids){
        if (Utils.isEmpty(ids)){
            return ResponseData.fail("id不能为空");
        }
        List<RefundVo> list = refundService.listVoByIds(ids);
        if (Utils.isEmpty(list)) {
            return ResponseData.fail("未获取到信息");
        }

        return ResponseData.success(list);
    }


    @ResponseBody
    @RequiresPermissions("refund:export")
    @RequestMapping("/refund/export")
    public ResponseData export(String close,
                               String search,
                               String no,
                               String saleNo,
                               String goodsName,
                               String remark,
                               String storeId,
                               String houseId,
                               String settAccountId,
                               String custom,
                               String makeTime1,
                               String makeTime2,
                               String userId,
                               String date1,
                               String date2,
                               String date,
                               String makeUserId,
                               String customId,
                               String status){
        Company company = getCompany();

        UserVo userVo = getLoginUserVo();
        List<RefundVo> refundVoList = refundService.listVo(company.getId(),
                null,
                null,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(saleNo),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                storeId,
                houseId,
                settAccountId,
                Utils.genLikeData(custom),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                PdosUtils.getViewOrderStoreId(userVo, null),
                PdosUtils.getViewOrderUserId(userVo, userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                makeUserId,
                customId,
                Utils.genInteger(status));

        String fileName = "销售退货单列表" + DateUtils.getDate(new Date(), DateUtils.YYYYMMDDHHMMSSSS) + ".xlsx";
        try {
            String path = FileProperUtil.getInstance().getVal("excel.temp");
            OutputStream out = new FileOutputStream(path+fileName);
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,true);
            Sheet sheet1 = new Sheet(1,0, ExcelRefund.class);
            sheet1.setSheetName("销售退货单信息");
            writer.write(genExcelList(refundVoList), sheet1);
            writer.finish();
            out.close();
            CleanTempExcelTask.put(fileName,new Date().getTime());
            return ResponseData.success(fileName);
        } catch (IOException e) {
            return ResponseData.fail("销售退货单列表导出失败");
        }
    }

    private List<ExcelRefund> genExcelList(List<RefundVo> refundVoList) {
        BusinessSet businessSet = getBusinessSet();
        List<ExcelRefund> list = new ArrayList<>();
        for (RefundVo vo : refundVoList){
            ExcelRefund excel = new ExcelRefund();
            excel.setDate(DateUtils.getDate(vo.getDate(), DateUtils.YYYY_MM_DD));
            excel.setNo(vo.getNo());
            excel.setLinkNo(vo.getSale()==null ? "": vo.getSale().getNo());
            excel.setCustomNo(vo.getCustom().getNo());
            excel.setCustomName(vo.getCustom().getName());
            String goods = "";
            BigDecimal number = new BigDecimal(0);
            BigDecimal amount = new BigDecimal(0);
            for (RefundGoodsVo refundGoodsVo : vo.getRefundGoodsVoList()){
                number = number.add(refundGoodsVo.getNumber());
                amount = amount.add(refundGoodsVo.getAmount());
                goods += refundGoodsVo.getGoodsVo().getName() + "、";
            }
            for (RefundPacketVo refundPacketVo : vo.getRefundPacketVoList()){
                number = number.add(refundPacketVo.getNumber());
                amount = amount.add(refundPacketVo.getAmount());
                goods += refundPacketVo.getPacketName() + "、";
            }

            goods = goods.substring(0,goods.length()-1);
            excel.setGoods(goods);
            excel.setNumber(PdosUtils.getNumber(number,businessSet));
            excel.setOldTotalAmt(PdosUtils.getNumber(amount,businessSet));
            excel.setOtherAmt(PdosUtils.getPrice(vo.getOtherAmt(),businessSet));
            excel.setTotalAmt(PdosUtils.getPrice(vo.getTotalAmt(),businessSet));
            excel.setRealAmt(PdosUtils.getPrice(vo.getRealAmt(),businessSet));
            excel.setUser(vo.getUser().getName());
            excel.setMakeUser(vo.getMakeUser().getName());
            if (vo.getType()==1){
                excel.setType("批发");
            } else {
                excel.setType("零售");
            }
            excel.setStore(vo.getHouseVo().getStore().getName());
            excel.setHouse(vo.getHouseVo().getName());
            excel.setRemark(vo.getRemark());
            excel.setClose(vo.getClose() ? "是":"否");
            list.add(excel);
        }
        return list;
    }

    private BigDecimal genPacketTotal(RefundPacketVo vo){
        BigDecimal total = new BigDecimal(0);

        for (RefundPacketGoodsVo pgv:vo.getPacketGoodsVoList()) {
            total = total.add(pgv.getAmount());
        }

        return total;
    }
}
